release: 7.75.0#29290
Merged
Merged
Conversation
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->
## **Description**
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
This makes the Rewards carousel match the Perps carousel.
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: null
## **Related issues**
Fixes: n/a
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
https://github.com/user-attachments/assets/a2021070-1b01-41b5-9d20-22ec5909d7cd
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Primarily UI/layout tweaks and copy changes to the Rewards tour
carousel, with a small test addition; low likelihood of impacting core
app flows beyond the onboarding screen.
>
> **Overview**
> Aligns the Rewards campaign tour carousel UI with the Perps carousel
by adjusting spacing/layout, left-aligning step text,
resizing/repositioning the optional image, and restyling the footer
(notably changing *Skip* from a secondary button to a centered text
link).
>
> Updates the primary CTA to show **"Let’s go"** on the last step (new
`rewards.onboarding.step_finish` i18n string), and adds a test to assert
the final-step label swap from `Next` to `Let’s go`.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
a7f0ba8. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…28839) ## **Description** The OTA workflow (`push-eas-update.yml`) had ~65 hardcoded environment variables in its YAML, duplicating what `builds.yml` already defines. This caused drift: the `exp` channel received production API defaults instead of dev/staging, new variables added to `builds.yml` were missing from OTA, and `MM_CHARTING_LIBRARY_URL` was incorrectly treated as a secret. This PR eliminates the duplication by having the OTA workflow read from `builds.yml` using the same `apply-build-config.js` + `set-secrets-from-config.js` pattern that native builds (`build.yml`) already use. I've confirmed that we don't need the following env variables for now: **QUICKNODE_BSC_URL QUICKNODE_SEI_URL** ## **Changelog** - **`push-eas-update.yml`**: Added a `prepare` job that maps channel → build name (e.g. `exp` → `main-exp`) and reads `builds.yml`. The `push-update` job now uses `apply-build-config.js` and `set-secrets-from-config.js` to set env vars and secrets, replacing the 65-line hardcoded env block with 7 OTA-specific vars. - **`builds.yml`**: Added 3 missing secrets that were only in the OTA workflow: `QUICKNODE_BSC_URL`, `QUICKNODE_SEI_URL`, `EXPO_TOKEN`. - **`build.sh`**: Moved `loadBuildConfig` outside the `expo-update` guard so OTA builds also load config from `builds.yml`. Replaced the hardcoded `createEnvFile()` var list with dynamic reads from `builds.yml`, eliminating a second source of duplication. **Key fix:** OTA updates to the `exp` channel will now correctly get `BRIDGE_USE_DEV_APIS=true`, `RAMPS_ENVIRONMENT=staging`, dev portfolio URLs, etc. — matching what `main-exp` native builds use. CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <img width="1080" height="2316" alt="Screenshot_20260417_030336_MetaMask" src="https://github.com/user-attachments/assets/11c87c4e-bba0-43bd-ab28-6d450d9c3535" /> ### **After** (should be the same as before) <img width="1080" height="2316" alt="Screenshot_20260416_021938_MetaMask" src="https://github.com/user-attachments/assets/78dd1e2e-227e-4ce8-ad9c-f4e6d9bc3429" /> <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes CI/release automation for OTA publishing and how secrets/env vars are sourced, so misconfiguration could break updates or target the wrong environment despite limited code-path impact. > > **Overview** > Migrates the OTA publish workflow to use `builds.yml` as the single source of truth for environment selection, non-secret env vars, and secret mappings, removing the large hardcoded env block from `push-eas-update.yml`. > > Adds a `prepare` job that maps OTA channel → build name (`main-exp`/`main-rc`/`main-prod`), sets the GitHub Environment dynamically, and passes the build’s secret mapping into `push-update`, which now applies config via `scripts/apply-build-config.js` and injects secrets via `scripts/set-secrets-from-config.js`. > > Updates `scripts/build.sh` so `expo-update` loads build config from `builds.yml` and generates `.env` dynamically from the keys defined in that build’s `env` + `secrets`; `builds.yml` is also extended to include `EXPO_TOKEN` in the shared secrets mapping. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 2fd32c0. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Small fixes <img width="1179" height="2556" alt="Simulator Screenshot - E2E Test - 2026-04-16 at 15 10 01" src="https://github.com/user-attachments/assets/4e810a60-0d84-4e2a-9b00-b9471fcf1b16" /> <img width="1179" height="2556" alt="Simulator Screenshot - E2E Test - 2026-04-16 at 15 35 01" src="https://github.com/user-attachments/assets/b7c0b4c3-63da-40f4-a6b8-f4ff320a71cb" /> <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [x] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [x] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.
#28944) ## **Description** The `Predict Feed Viewed` event tracks where users navigate from via an `entry_point` property. When users tapped into the Predict Feed from the homepage Predictions section (trending markets carousel, no active positions), no `entry_point` value was being passed. The property was absent from the event. This PR adds a new `home_section` entry point value and wires it into the homepage navigation handler that leads to the Predict Feed. ## **Changelog** CHANGELOG entry:null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TMCU-609 ## **Manual testing steps** ```gherkin Feature: Predict Feed Viewed entry_point from homepage Scenario: user navigates to Predict Feed from homepage with no positions Given the user has no active Predict positions And the user is on the Wallet homepage When user taps the "Predictions" section header title Then the Predict Feed opens And a "Predict Feed Viewed" event is fired with entry_point: "home_section" ``` ## **Screenshots/Recordings** https://github.com/user-attachments/assets/3682b1d8-6c9a-4330-985f-8bc0e605c3dd ### **Before** `~` ### **After** `~` ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Small analytics/navigation parameter change scoped to the Predict homepage entry point with unit test coverage; minimal functional impact beyond event attribution. > > **Overview** > Ensures the `Predict Feed Viewed` analytics `entry_point` is populated when users enter the Predict market list from the homepage Predictions section. > > This introduces a new `PredictEventValues.ENTRY_POINT.HOME_SECTION` value, extends the `PredictEntryPoint` type to include it, and updates the homepage Predictions navigation handler to pass `entryPoint: home_section` when tapping the section title (with tests updated/added to assert the new navigation params). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit c366553. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## Version Bump After Release This PR bumps the main branch version from 7.74.0 to 7.75.0 after cutting the release branch. CHANGELOG entry: null ### Why this is needed: - **Nightly builds**: Each nightly build needs to be one minor version ahead of the current release candidate - **Version conflicts**: Prevents conflicts between nightlies and release candidates - **Platform alignment**: Maintains version alignment between MetaMask mobile and extension - **Update systems**: Ensures nightlies are accepted by app stores and browser update systems ### What changed: - Version bumped from `7.74.0` to `7.75.0` - Platform: `mobile` - Files updated by `set-semvar-version.sh` script ### Next steps: This PR should be **manually reviewed and merged by the release manager** to maintain proper version flow. ### Related: - Release version: 7.74.0 - Release branch: release/7.74.0 - Platform: mobile - Test mode: false --- _This PR mirrors the process used in #28357 (`chore(release): Bump main version to 7.74.0`)._ Made with [Cursor](https://cursor.com) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > <sup>[Cursor Bugbot](https://cursor.com/bugbot) is generating a summary for commit a623ae0. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description**
Migrate the Predict Buy and Sell preview screens from full-screen stack
navigation into BottomSheet wrappers, gated behind the
`predictBottomSheet` LaunchDarkly feature flag. When the flag is OFF,
the existing full-screen navigation flow is preserved with zero
behavioral changes.
### What changed
**New: `PredictPreviewSheet` wrapper component**
- Generic BottomSheet wrapper that renders buy/sell preview content as
children.
- Uses `BottomSheet`, `BottomSheetHeader`, and
`BottomSheetHeaderVariant` from `@metamask/design-system-react-native`
(not the deprecated component-library version).
- Supports `renderHeader` prop for custom header content (sell sheet
uses it for rich cashout info); falls back to default
icon+title+subtitle layout (buy sheet).
- `isFullscreen` prop controls sheet height: content-fitted for both buy
and sell sheets (auto-sizes to content).
- Title and subtitle elements expose `testID` props
(`preview-sheet-title`, `preview-sheet-subtitle`) for testID-based
assertions.
- Unit tests for the wrapper component.
**New: `PredictPreviewSheetContext` (central sheet state manager)**
- Context provider manages both buy and sell sheet refs, params, and
open/close lifecycle.
- Exposes `openBuySheet()` / `openSellSheet()` methods consumed by all
card components.
- Feature flag check determines whether to navigate (old flow) or open a
sheet (new flow).
- `SellSheetHeader` extracted as a standalone component within the
context for the rich header.
- Graceful fallback: `usePredictPreviewSheet()` returns navigation-based
routing when used outside the provider (e.g. home carousel, trending
feed) instead of throwing, with memoized references to prevent
unnecessary re-renders.
- Nonce-based re-open mechanism to handle identical params across
consecutive sheet opens.
- Unit tests for the context provider.
**New: `predictBottomSheet` feature flag**
- Registered in `feature-flag-registry.ts` as a remote, version-gated
flag (default: disabled).
- New selector `selectPredictBottomSheetEnabledFlag` in
`selectors/featureFlags/index.ts`.
**New: `PredictQuickAmounts` component (with haptic feedback)**
- Standalone quick-pick buttons ($20, $50, $100, $250) displayed in the
bottom content area of the buy sheet.
- Uses `expo-haptics` (`impactAsync` with `ImpactFeedbackStyle.Light`)
for tactile feedback on button press. `impactAsync` is properly awaited
with error swallowing for unsupported devices.
- Quick amounts set the input to whole numbers (e.g. `"20"` not
`"20.00"`) for easier editing.
- Disabled buttons are verified non-functional in tests.
- Uses design-system `Box` component instead of raw `View`.
- Unit tests including haptic feedback verification and async handler
coverage.
**New: `usePredictCashOut` hook (shared cashout logic)**
- Encapsulates the guarded cashout action flow: find outcome by
`position.outcomeId`, call `openSellSheet`, and handle errors with
`Logger.error` + toast notification.
- Accepts `market` and `callerName` parameters; `callerName` is included
in error metadata for production diagnostics.
- Consumed by both `PredictPicks` and `PredictPositionDetail`,
eliminating ~40 lines of identical code from each.
- Exported from `hooks/index.ts`.
- Unit tests covering guarded action invocation, `openSellSheet` params,
error/toast on missing outcome, and `callerName` in metadata.
**Navigation migration (10 components updated)**
All components that previously called `navigateToBuyPreview()` /
`navigate(Routes.PREDICT.MODALS.SELL_PREVIEW)` now call `openBuySheet()`
/ `openSellSheet()` from `usePredictPreviewSheet`:
- `PredictMarketDetails` - outcome buy actions
- `PredictMarketSingle` - Yes/No buy buttons
- `PredictMarketMultiple` - outcome buy buttons
- `PredictMarketOutcome` - price buttons
- `PredictSportCardFooter` - feed card buy actions
- `FeaturedCarouselCard` - carousel card outcome buy buttons
- `FeaturedCarouselSportCard` - sport carousel card buy buttons
- `PredictPicks` - cashout from picks list via shared
`usePredictCashOut` hook
- `PredictPositionDetail` - cashout from position detail via shared
`usePredictCashOut` hook
- Removed direct dependency on `usePredictNavigation` from all these
components.
**Routes (`routes/index.tsx`)**
- Wrapped the stack navigator with `PredictPreviewSheetProvider` so
sheets are available throughout the Predict navigation tree.
**Buy sheet (`PredictBuyWithAnyToken`)**
- Uses discriminated union props (`mode: 'sheet' | 'screen'`) for
type-safe sheet vs navigation mode, replacing `Partial<ContentProps>`
with `as` casts.
- Sheet mode layout: header hidden (provided by `PredictPreviewSheet`),
`PredictQuickAmounts` in bottom content, `PredictPayWithRow` in compact
`variant="row"` mode with balance display, keypad moved below bottom
content with `hideHeader`, border hidden, action button displays
"Confirm".
- Uses `Box` wrapper instead of `SafeAreaView` in sheet mode.
- `PredictPayWithAnyTokenInfo` receives `isInputFocused: false` in sheet
mode to ensure mm_pay relay configuration runs immediately (prevents
underfunded deposit).
- Sheet cleanup: unmount runs `onReject` +
`clearActiveOrderTransactionId` (matches `beforeRemove` behavior in old
flow).
- Approval request recovery: when `approvalRequest` is missing during
`handleConfirm` in PAY_WITH_ANY_TOKEN state, attempts re-initialization
via `initPayWithAnyToken()` (clears `batchIdRef`, rejects pending
transactions, re-creates the approval) before returning
`PLACE_ORDER_FAILED`. This gives the user a chance to retry with a fresh
approval rather than silently failing.
**Buy sheet (`PredictBuyPreview` - legacy non-pay-with-any-token)**
- Same discriminated union props / `isSheetMode` pattern for BottomSheet
compatibility.
- Header and back button hidden in sheet mode; close action routed to
`onClose()`.
- Uses `ScrollView` from `react-native-gesture-handler` (aliased as
`GHScrollView`) in sheet mode to cooperate with the BottomSheet's
`PanGestureHandler`; standard React Native `ScrollView` preserved for
the full-screen path.
**Sell sheet (`PredictSellPreview`)**
- Same discriminated union props pattern; `isSheetMode` drives
conditional layout: icon+title row hidden in sheet mode (rendered by
`SellSheetHeader` in the sheet header instead), price/shares/PnL section
relocated to the bottom area.
- Sheet mode uses inline Tailwind `tw.style('flex-col')` instead of
`StyleSheet.create()` for the container.
- Extracted `getCashoutInfoText` helper into `utils/format.ts` to DRY up
the localized cashout info string.
**`PredictController` (batch transaction fix)**
- Added `gasFeeToken: MATIC_CONTRACTS.collateral` to the
`initPayWithAnyToken` batch submission, matching other batch calls. This
ensures mm_pay configures the relay step to bridge funds when the Safe
has insufficient USDC balance.
**`PredictKeypad`**
- New `hideHeader` prop to suppress the quick-amount row + Done button
when rendered inside the buy sheet (avoids duplication with
`PredictQuickAmounts`).
**`PredictPayWithRow`**
- New `variant="row"` mode: compact single-row layout showing token
icon, symbol, balance, and right chevron for the sheet.
- New `availableBalance` prop for displaying balance in row mode.
**`PredictBuyAmountSection`**
- New `hideAvailableBalance` prop to suppress the "Available: $X.XX"
text in sheet mode.
**`PredictBuyBottomContent`**
- New `hideBorder` prop to remove the top border separator in sheet
mode.
- Restored inline text wrapping for the disclaimer + "Learn more" link
(nested `Text` instead of sibling flex items).
**`PredictBuyActionButton`**
- New `isSheetMode` prop: when true, displays "Confirm" label instead of
"{outcome} · {price}".
**`PredictFeeSummary`**
- Removed "incl. fees" subtitle text; moved info icon inline next to
"Total" on the same line.
- Total amount typography changed from `HeadingMd`/`Bold` to
`BodyMd`/`Medium` to match Pay With row.
**Bug fixes**
- `usePredictBuyConditions`: Auto-revert effect that switched back to
Predict balance now requires `totalPayForPredictBalance > 0`, preventing
immediate revert when the amount is 0 (which always caused the payment
method selection to snap back in sheet mode).
- `usePredictBuyConditions`: `shouldWaitForPayFees` now also requires
`currentValue > 0`.
- `usePredictBuyActions`: When `approvalRequest` is missing during
`handleConfirm` in PAY_WITH_ANY_TOKEN state, attempts re-initialization
(`initPayWithAnyToken()`) before returning early with error, giving the
user a retry path rather than silently failing. Removed dead fallback
branch that was unreachable (transactionId derived from the same
approvalRequest).
- `usePredictBuyActions`: `batchIdRef` cleared at the start of
`doInit()` to prevent stale values between transaction attempts.
- `usePredictBuyActions`: Sheet unmount cleanup mirrors `beforeRemove`
behavior from the old flow.
- `usePredictBuyActions`: DEPOSITING and SUCCESS state effects check
`isSheetMode` to call `onClose()` instead of `StackActions.pop()`.
- `usePredictBuyError`: Removed `isInputFocused` from the
`blockingPayAlertMessage` gate. The flag was permanently suppressing
insufficient-funds errors in sheet mode because `isInputFocused`
initialized to `true` and never transitioned to `false` when using
quick-amount buttons. The `isPayFeesLoading` check already handles
stale-data concerns.
- `PredictPicks` / `PredictPositionDetail`: Cashout logic (outcome
lookup, `openSellSheet`, error handling with `Logger.error` + toast)
extracted into shared `usePredictCashOut` hook to eliminate duplication.
- `PredictPayWithAnyTokenInfo`: `isInputFocused` overridden to `false`
in sheet mode so `updatePendingAmount` and `setPayToken` run
immediately, ensuring mm_pay relay step is configured before
confirmation.
- `PredictController`: Added `gasFeeToken` to `initPayWithAnyToken`
batch to fix missing mm_pay relay step that caused "Insufficient USDC
balance in Safe" errors.
- `PredictPreviewSheetContext`: Stabilized `onDismiss` callbacks with
`useCallback` to prevent unstable `closeSheet`/`onClose` references from
causing repeated SUCCESS/DEPOSITING effect re-fires.
**Code quality**
- Extracted shared `usePredictCashOut` hook to deduplicate identical
`onCashOut` logic (~40 lines each) from `PredictPicks` and
`PredictPositionDetail`. Both components now use a single hook call
instead of duplicating the guarded action, outcome lookup,
`openSellSheet` call, and error handling with `Logger.error` + toast.
The `callerName` parameter preserves per-component error metadata.
- Replaced raw `View` with design-system `Box` in `PredictQuickAmounts`.
- Removed stale comments from `usePredictBottomSheet`.
- Discriminated union types (`PredictBuyPreviewProps`,
`PredictSellPreviewProps`) replace `Partial<ContentProps>` with `as`
casts, providing compile-time safety for sheet vs navigation mode.
- New test IDs: `BUY_PREVIEW_SHEET`, `SELL_PREVIEW_SHEET`.
- Memoized fallback return value in `usePredictPreviewSheet` to prevent
unstable function references.
- Memoized `BuyComponent` selection in `PredictPreviewSheetContext` with
`useMemo` to prevent unnecessary unmount/remount cycles.
- Added `index.ts` barrel export for `PredictPreviewSheet` component
(file organization standard).
- Restored slide-from-right `cardStyleInterpolator` on `BUY_PREVIEW` and
`SELL_PREVIEW` stack screens for the flag-OFF full-screen path.
- Replaced `require()` with `jest.requireActual()` in all test mock
factories.
- Fixed module-level shared mutable state (`navigationRef`) in
`routes/index.test.tsx` — moved to `beforeEach`.
- Strengthened test assertions in `PredictMarketDetails.test.tsx` to
verify exact call parameters with `expect.objectContaining()`.
- Removed dead/unused `predict.order.buy` i18n key and its stale test
mock reference.
- Migrated `PredictPreviewSheet` from deprecated component-library
`BottomSheet` to `@metamask/design-system-react-native`
`BottomSheet`/`BottomSheetHeader` (DS-first UI rule). Updated
`usePredictBottomSheet` hook to import `BottomSheetRef` from DS.
- Replaced `shouldNavigateBack={false}` with DS equivalent (omit
`goBack` prop); changed header `style` prop to `twClassName`.
- `PredictBuyPreview`: Uses gesture-handler-aware `ScrollView` from
`react-native-gesture-handler` in sheet mode to prevent scroll/dismiss
conflicts with the BottomSheet's `PanGestureHandler` on Android.
- Replaced all `toBeNull()` assertions with `not.toBeOnTheScreen()` in
test files per unit-test guidelines.
- Replaced text-based queries (`getByText`, `queryByText`) with
testID-based assertions (`getByTestId` + `toHaveTextContent`) in
`PredictPreviewSheet.test.tsx` and
`PredictPreviewSheetContext.test.tsx`.
- Changed synchronous `act()` to `await act(async () => { ... })` in
`routes/index.test.tsx` to flush async navigator state updates and
eliminate act() warnings.
**Localization**
- Added `predict.odds` key ("Odds").
- Added `predict.order.confirm` key ("Confirm") for the sheet action
button.
- Removed unused `predict.order.buy` key ("Buy {{outcome}}").
**Documentation**
- Added comprehensive Predictions architecture guide
(`docs/predict/predictions-comprehensive-guide.md`).
- Added ticket documentation
(`docs/predict/tickets/buy-sell-bottomsheet-migration.md`).
## **Changelog**
CHANGELOG entry: null
## **Related issues**
Refs:
[PRED-707](https://consensyssoftware.atlassian.net/browse/PRED-707?atlOrigin=eyJpIjoiZGU2Y2YwN2RlMWJjNDZiNmJkYjdkMmQwMzQ2ZDFmZmMiLCJwIjoiaiJ9)
## **Manual testing steps**
```gherkin
Feature: Predict Buy/Sell BottomSheet Migration
Scenario: Buy prediction via bottom sheet (flag ON)
Given the predictBottomSheet feature flag is enabled
And the user is on a prediction market details page
When user taps a "Yes" or "No" outcome button
Then a bottom sheet opens with the buy preview content
And the sheet header shows the outcome icon, "Yes/No · Outcome Name" title, and odds subtitle
And quick amount buttons ($20, $50, $100, $250) are visible with haptic feedback
And the user can enter an amount, select payment method, and tap "Confirm"
And the order is placed successfully
And the sheet closes after the deposit is initiated
Scenario: Sell position via bottom sheet (flag ON)
Given the predictBottomSheet feature flag is enabled
And the user has an active position on a market
When user taps "Cash out" on their position
Then a content-fitted bottom sheet opens (not fullscreen)
And the sheet header shows the position icon, title, and cashout info
And the body shows the current value, shares, PnL, and Cash out button
And tapping "Cash out" places the sell order and closes the sheet
Scenario: Buy prediction via full-screen navigation (flag OFF)
Given the predictBottomSheet feature flag is disabled
And the user is on a prediction market details page
When user taps a "Yes" or "No" outcome button
Then the app navigates to the full-screen BuyPreview screen
And the existing layout and behavior are unchanged
Scenario: Sell position via full-screen navigation (flag OFF)
Given the predictBottomSheet feature flag is disabled
And the user has an active position on a market
When user taps "Cash out" on their position
Then the app navigates to the full-screen SellPreview screen
And the existing layout and behavior are unchanged
Scenario: Change payment method in buy sheet (flag ON)
Given the predictBottomSheet feature flag is enabled
And the buy bottom sheet is open
When user taps the Pay with row and selects a different token (e.g. USDC)
Then the payment method updates and stays selected
And the fee summary and total update accordingly
Scenario: Buy from feed cards and carousel (flag ON)
Given the predictBottomSheet feature flag is enabled
And the user is on the Predict feed or homepage carousel
When user taps a Yes/No button on any market card
Then the bottom sheet opens with the correct market/outcome pre-filled
And the flow works identically to opening from market details
Scenario: Components outside PredictScreenStack (flag ON)
Given the predictBottomSheet feature flag is enabled
And a Predict card is rendered on the homepage carousel (outside PredictScreenStack)
When user taps a Yes/No button
Then the app navigates via React Navigation (fallback behavior)
And no crash occurs from missing PredictPreviewSheetProvider
Scenario: Quick amount haptic feedback (flag ON)
Given the buy bottom sheet is open
When user taps a quick amount button ($20, $50, $100, or $250)
Then haptic feedback fires (Light impact)
And the amount input updates to the selected value
And the input unfocuses
```
## **Screenshots/Recordings**
### **Before**
Full-screen buy/sell preview navigation (flag OFF) - no visual changes
to this flow.
### **After**
https://github.com/user-attachments/assets/1e365eeb-74bf-4281-a415-0453606c5d80
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
[PRED-707]:
https://consensyssoftware.atlassian.net/browse/PRED-707?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Touches Predict trade entry points and preview/cash-out flows, plus
introduces a new feature-flagged UI layer; regressions could affect
order preview UX or sheet/navigation behavior, though the legacy route
path remains as fallback.
>
> **Overview**
> Adds a new feature-flagged bet slip flow for Predict by introducing
`PredictPreviewSheet` +
`PredictPreviewSheetProvider`/`usePredictPreviewSheet`, allowing
buy/sell previews to open in BottomSheets (with navigation fallback when
the provider/flag isn’t available).
>
> Updates multiple Predict entry points (feed cards, carousel cards,
market single/multiple/outcome components, and sport footer) to call
`openBuySheet` instead of navigating to the buy preview, and refactors
cash-out handling into a shared `usePredictCashOut` hook that opens the
sell sheet and handles missing-outcome errors via logging + toast.
>
> Extends buy preview screens (`PredictBuyPreview`,
`PredictBuyWithAnyToken`) to support a new `mode: 'sheet'` rendering
path (layout tweaks, keypad/header behavior, confirm CTA), adds new test
IDs/feature-flag selectors (`predictBottomSheet`), and adjusts provider
order result shape and assorted tests to match the new behavior.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
ca83caf. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Caainã Jeronimo <caainaje@gmail.com>
Co-authored-by: Luis Taniça <matallui@gmail.com>
## **Description**
Fixes the token advanced chart staying scrolled back in time when users
pan and then change the time range quickly. Also avoids sending previous
range OHLCV into the WebView while the new fetch is still in flight
**Problem**
Viewport / scroll — TradingView keeps pan/scroll state inside the
WebView. Changing range without a full new surface could reuse that
state, so the chart looked wrong after a fast time-range change.
Stale data — useOHLCVChart keeps the last ohlcvData until the new
request completes. Right after a range change, props can show the new
ohlcvSeriesKey but the old candle array (same reference). Sending that
as SET_OHLCV_DATA for the new range causes bad data / races.
**Solution**
WebView key — Tie key to ohlcvSeriesKey (with ?? '' when the prop is
omitted) so each series change remounts the WebView and drops inherited
TradingView scroll state.
ohlcvSeriesStaleSnapshotRef + guard — When the series key changes but
ohlcvData is still the previous array reference, don’t sync full OHLCV;
wait until the hook returns a new array reference, then send.
useEffect on ohlcvSeriesKey — Reset loading / ready state
(chartReadyCount, webViewLoaded, layout settle timers) and clear
ohlcvSeriesStaleSnapshotRef. Reset activeIndicatorsRef,
prevPositionLinesRef, and prevChartTypeRef so the new WebView gets
indicators, position lines, and chart type (line vs candles) applied
correctly without a default-candles flash.
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: Fixes race condition on timeRange switch
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
Uploading Screen Recording 2026-04-16 at 23.39.54.mov…
### **After**
<!-- [screenshots/recordings] -->
Uploading Screen Recording 2026-04-17 at 00.10.19.mov…
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Touches chart lifecycle/sync logic and WebView remount behavior, which
could regress loading/skeleton timing or data updates across range
switches if edge cases weren’t covered.
>
> **Overview**
> Fixes a race on time-range changes in `AdvancedChart` by **remounting
the WebView** when `ohlcvSeriesKey` changes (via a `key`) and resetting
“ready/loading/layout settle” state so the new instance re-applies
indicators, position lines, and chart type deterministically.
>
> Adds a **stale-series guard** (`ohlcvSeriesStaleSnapshotRef`) that
suppresses `SET_OHLCV_DATA` syncing when the series key updates but
`ohlcvData` is still the previous array reference, resuming only once
fresh data arrives; updates tests to reflect the WebView remount/load
sequence and stale-data wait behavior.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f7a52c7. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description** This restores the `myxModulePath` workaround in mobile `PerpsController` so the mobile source of truth matches the safe Core pattern from `core#8424`, and it hardens `scripts/perps/validate-core-sync.sh` plus the `perps-core-sync` skill so future syncs fail if the built Core publish artifact loses the `webpackIgnore` safeguard again. This branch has been refreshed onto a `main` that already includes #28865, so no separate follow-up is still pending for the historical candle transport fix. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: - Related to MetaMask/core#8424 - Related to MetaMask/core#8460 - Related to MetaMask/core#8473 - Related to MetaMask/metamask-extension#41558 - Refreshed onto `main` after #28865 merged ## **Manual testing steps** ```gherkin Feature: preserve MYX publish safety during mobile-to-core sync Scenario: validate the sync guard on a clean Core checkout Given mobile is on this branch and Core is checked out locally When I run `bash scripts/perps/validate-core-sync.sh --core-path <core-path> --skip-test` Then the copied-source validation reaches the publish-artifact gate And the run fails if the built Core artifact does not preserve the MYX webpackIgnore safeguard Scenario: validate the perps historical candle transport coverage that is already present on main When I run `yarn jest app/controllers/perps/services/HyperLiquidClientService.test.ts --no-coverage` Then the TAT-2954 historical candle HTTP transport coverage passes ``` ## **Screenshots/Recordings** ### **Before** N/A - controller/source-sync change only. ### **After** N/A - controller/source-sync change only. ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - [ ] I've tested with a power user scenario - [ ] I've instrumented key operations with Sentry traces for production performance metrics ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.
…0.0 (#28950) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Bumps - @metamask/gator-permissions-controller from ^3.0.0 to ^4.0.0 - @metamask/signature-controller from ^39.1.2 to ^39.2.0 <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Although the diff is dependency-only, it upgrades a major version of the permissions controller and updates signature-related transitive controllers, which could change runtime behavior in permission/signing flows. > > **Overview** > Updates dependencies to use `@metamask/gator-permissions-controller` `^4.0.0` (from `^3.0.0`) and `@metamask/signature-controller` `^39.2.0` (from `^39.1.2`). > > Refreshes `yarn.lock` for the new controller versions and their updated transitive requirements (notably newer `@metamask/*` controller/messenger packages). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 2b3b762. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->
## **Description**
Updates the margin bottom of advanced chart in token details page to
avoid price scale tick being clipped.
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: null
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
<img width="529" height="546" alt="Screenshot 2026-04-17 at 01 58 23"
src="https://github.com/user-attachments/assets/2571fe52-d1b1-4ed6-bef7-1f89eaac6d02"
/>
### **After**
<!-- [screenshots/recordings] -->
<img width="424" height="511" alt="Screenshot 2026-04-17 at 01 58 35"
src="https://github.com/user-attachments/assets/050994a8-abc1-49e6-91d1-a8e1ad562fba"
/>
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Pure UI/layout tweak to chart overrides plus formatting-only changes;
no business logic, data handling, or security-sensitive code is
affected.
>
> **Overview**
> Adjusts TradingView override layout by increasing
`paneProperties.bottomMargin` from `8` to `9` in both the runtime
WebView script (`chartLogic.js`) and its injected string source
(`chartLogicString.ts`) to prevent right price-scale tick labels from
being clipped.
>
> Includes a couple of no-op formatting/whitespace-only edits in
`chartLogicString.ts` (line wrapping and blank line normalization).
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
588ef84. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->
## **Description**
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
Removed the unused ESTIMATED_FEE_RATE export from the perps HyperLiquid
config after the reverse position fee precheck logic was deleted.
The constant was previously only used for a stale entry price based
local fee estimate in flipPosition(), and once that logic was removed it
became dead code with no remaining references.
The improvement is a small cleanup that keeps the perps config aligned
with actual runtime usage and avoids carrying an orphaned fee constant
that no longer drives any validation or execution behavior.
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: null
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Pure cleanup removing an unused constant with no runtime behavior
changes, aside from potential breakage for any external imports of
`ESTIMATED_FEE_RATE`.
>
> **Overview**
> Removes the unused `ESTIMATED_FEE_RATE` export from
`hyperLiquidConfig.ts`, eliminating dead configuration now that fee
precheck/flip estimation logic is gone.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
744640b. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
#28894) ## **Description** Add browser navigation E2E tests with local fixtures to replace quarantined tests from `browser-tests.failing.ts`. Three tests cover: 1. **Invalid URL** — navigates to a non-existent URL and verifies the browser returns home 2. **ENS resolution** — resolves `vitalik.eth` via mocked ENS/IPFS and verifies the fixture page loads 3. **Cross-origin redirect** (`it.skip`) — loads a redirect page on one dapp server that navigates to a second dapp server, verifying the URL bar updates. Skipped due to an app-level bug where `BrowserTab.handleSuccessfulPageResolution` does not update the URL bar after JS-initiated cross-origin redirects ([MCWP-540](https://consensyssoftware.atlassian.net/browse/MCWP-540)). Part of the browser tests migration effort (MMQA-1368) to move quarantined E2E tests from external URLs to local HTML fixtures with API mocking. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: [MMQA-1721](https://consensyssoftware.atlassian.net/browse/MMQA-1721) Related app bug: [MCWP-540](https://consensyssoftware.atlassian.net/browse/MCWP-540) ## **Manual testing steps** ```gherkin Feature: Browser Navigation Scenario: user visits an invalid URL and returns home Given the user is logged in and on the browser tab When user navigates to an invalid URL (https://quackquakc.easq) And user taps the Return Home button Then the URL bar no longer shows the invalid URL origin Scenario: user resolves an ENS domain Given the user is logged in and on the browser tab And ENS resolution is mocked to return a local fixture via IPFS gateway When user navigates to vitalik.eth Then the ENS fixture page loads with a General link Scenario: user follows a cross-origin redirect (skipped) Given the user is logged in and on the browser tab And two local dapp servers are running with redirect fixtures When user navigates to a redirect page on dapp server 1 Then the URL bar shows the origin of dapp server 1 When the page redirects to dapp server 2 Then the URL bar shows the origin of dapp server 2 # Skipped: app bug MCWP-540 — URL bar does not update after JS cross-origin redirect ``` ## **Screenshots/Recordings** ### **Before** N/A — new tests, no prior implementation ### **After** **Android (Pixel 9)** ``` PASS tests/smoke/wallet/browser/browser-navigation.spec.ts (267.195 s) SmokeWalletPlatform: Browser Navigation ✓ navigates back home after visiting an invalid URL (92816 ms) ✓ resolves and displays ENS website (vitalik.eth) (76344 ms) ○ skipped: displays redirected URL after cross-origin redirect Test Suites: 1 passed, 1 total Tests: 1 skipped, 2 passed, 3 total ``` **iOS (iPhone 16 Pro)** ``` PASS tests/smoke/wallet/browser/browser-navigation.spec.ts (260.222 s) SmokeWalletPlatform: Browser Navigation ✓ navigates back home after visiting an invalid URL (102674 ms) ✓ resolves and displays ENS website (vitalik.eth) (71537 ms) ○ skipped: displays redirected URL after cross-origin redirect Test Suites: 1 passed, 1 total Tests: 1 skipped, 2 passed, 3 total ``` ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. [MCWP-540]: https://consensyssoftware.atlassian.net/browse/MCWP-540?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [MMQA-1721]: https://consensyssoftware.atlassian.net/browse/MMQA-1721?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [MCWP-540]: https://consensyssoftware.atlassian.net/browse/MCWP-540?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…vigation v6 cp-7.73.0 cp-7.74.0 (#28814) --- ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> React Navigation v6's JS-based `@react-navigation/stack` creates Reanimated shared values during render before the Fabric commit is finalized. Under the New Architecture (`newArchEnabled=true`, RN 0.76.9), this causes animations to fall back to the JS thread, producing a freeze-then-snap jitter when navigating into the Perps stack. The fix replaces `createStackNavigator` with `createNativeStackNavigator` (from `@react-navigation/native-stack@^6`) for `PerpsScreenStack`. Native stack transitions run as pure UIKit (iOS) / Fragment (Android) animations with zero Reanimated/JS-thread involvement, eliminating the timing issue entirely. Concretely: - Added `@react-navigation/native-stack@^6` as a dependency (compatible with the existing `react-native-screens@3.37.0`) - Replaced `createStackNavigator` → `createNativeStackNavigator` for the inner Perps navigator in `routes/index.tsx` - Updated screen option syntax for the two transparent-modal screens: `cardStyle` → `contentStyle`, `animationEnabled: false` → `animation: 'none'`, and replaced JS-stack-only `header`/`headerLeft` callbacks with `headerShown`/`headerBackVisible` - Updated the Perps ROOT entry in `MainNavigator.js` to use `TransitionPresets.SlideFromRightIOS`, replacing the hand-rolled `cardStyleInterpolator` that used `Animated.Value.interpolate` with `layouts.screen.width` (which can be 0 on first render under Fabric's async layout) ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` --> CHANGELOG entry: Fixed jittery navigation transitions when opening Perps on devices running the New Architecture ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: Perps navigation transition Scenario: User navigates to Perps from wallet home Given the user is on the Wallet home screen with the Perps tab visible And the device is running the New Architecture (newArchEnabled=true) When the user taps "New Trade" or any button that navigates to Perps Then the screen transitions immediately with a smooth slide-from-right animation And no freeze-then-snap jitter occurs during the transition And the Perps home screen content appears correctly after the transition Scenario: User navigates between Perps screens Given the user is on the Perps home screen When the user taps on a market to open market details Then the transition to the market details screen is smooth and immediate And navigating back to Perps home is also smooth ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** N/A ### **After** https://github.com/user-attachments/assets/62736a87-d18d-4b9e-bffe-5969a2855ccf https://github.com/user-attachments/assets/7f672b9f-7386-4274-bb7b-1ff8d0bb87a1 ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- Generated with the help of the pr-description AI skill --> Made with [Cursor](https://cursor.com) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes navigation primitives and header behavior for the Perps flow, which can affect transitions, modal presentation, and confirmation screen UX if options are mis-mapped between stack implementations. > > **Overview** > Fixes Perps navigation jitter under React Navigation v6 / RN New Architecture by switching the Perps inner navigator from JS `@react-navigation/stack` to `@react-navigation/native-stack`. > > Updates Perps screen options to native-stack equivalents (`contentStyle`, `animation: 'none'`, `presentation: 'transparentModal'`) and adds a scoped `NavigationContext` override in `PerpsConfirmScreen` to prevent `Confirm` from re-enabling a header when `showPerpsHeader` is false. Also ensures the Perps root entry in `MainNavigator` explicitly disables the header. > > Bumps mobile build numbers (`versionCode` / `CURRENT_PROJECT_VERSION`) and Bitrise `VERSION_NUMBER` to `4532`, and adds the `@react-navigation/native-stack` dependency. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit c92d05c. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** The trader profile StatsRow currently shows a dash placeholder for avg hold time with the label "avg. hold". ### Changes - Rename the label from "avg. hold" to "hold time" in i18n strings - Wire up medianHoldingTimeMinutes from the social controller/API response to the StatsRow component - The StatsRow component already accepts an avgHoldMinutes prop and formats it — just needs to be passed from TraderProfileView [TSA-408](https://consensyssoftware.atlassian.net/browse/TSA-408) <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Added hold time to trader profile view ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk UI/i18n wiring change plus a minor dependency bump; main risk is mismatched API fields from `@metamask/social-controllers@0.2.0` causing hold time or follow-state defaults to regress. > > **Overview** > **Trader profile stats now display hold time from the API** by wiring `profile.stats.medianHoldMinutes` into `StatsRow` via a renamed prop (`holdTimeMinutes`). > > Updates the i18n label from `avg. hold` to `hold time`, adjusts `StatsRow` unit tests accordingly, and bumps `@metamask/social-controllers` to `^0.2.0` (updating default background/log snapshot state to include `SocialController.followingProfileIds`). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 6de3166. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> [TSA-408]: https://consensyssoftware.atlassian.net/browse/TSA-408?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --------- Co-authored-by: Joao Santos <jrmsantos15@gmail.com> Co-authored-by: Antonio Regadas <antonio.regadas@consensys.net> Co-authored-by: Xavier Brochard <xavier.brochard@consensys.net>
## **Description**
Adds the `no_orders` translation string ("You do not have any open
orders") to the perps locale section. This supports displaying a
user-friendly empty state message when there are no open orders in the
perpetuals trading view.
## **Changelog**
CHANGELOG entry: null
## **Related issues**
Fixes: https://consensyssoftware.atlassian.net/browse/TAT-2967
## **Manual testing steps**
```gherkin
Feature: Perps open orders empty state
Scenario: User views open orders when none exist
Given the user is on the perpetuals trading view
And the user has no open orders
When the user navigates to the orders tab
Then the user sees a "You do not have any open orders" message
```
## **Screenshots/Recordings**
N/A — locale string addition only, no UI change in this PR.
### **Before**
### **After**
<img width="1320" height="2868" alt="Simulator Screenshot - iPhone 17
Pro Max - 2026-04-17 at 11 21 57"
src="https://github.com/user-attachments/assets/49d4cb83-a1f7-4fc6-9aaf-5afec110bb62"
/>
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk: adds a single i18n string with no logic or behavioral
changes.
>
> **Overview**
> Adds a new perps order locale entry, `no_orders`, with the message
"You do not have any open orders" to support an open-orders empty state.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
6a45f62. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**
Fixes several issues that prevent Detox e2e specs from running correctly
in local debug builds:
1. **`.detoxrc.js`** — Allow `IOS_SIMULATOR` env var to override the
hardcoded `iPhone 16 Pro` device type. Falls back to the default when
unset, so CI is unaffected.
2. **`tests/helpers.js` — launch detection** — The original
`endsWith('debug')` check never matched any Detox configuration name
(`ios.sim.main`, `ios.sim.flask`, `ios.sim.apiSpecs`), so
`launchAppForDebugBuild` was never called locally. This PR keeps the
original `endsWith('debug')` check for backwards compatibility and adds
`!endsWith('.ci')` as a fallback, so all non-CI configs (which use debug
apps like `ios.debug`) correctly route through `launchAppForDebugBuild`.
CI configs (`ios.sim.main.ci`, `ios.sim.flask.ci`) are unaffected — they
still use `launchAppWithRecovery` with release apps.
3. **`tests/helpers.js` — packager URL** — Use `METRO_PORT_E2E` /
`WATCHER_PORT` for the packager URL instead of hardcoded `8081`.
`METRO_PORT_E2E` remains the primary source, `WATCHER_PORT` is a
fallback for local `.js.env` config.
4. **`tests/flows/general.flow.ts`** — Add `WATCHER_PORT` as fallback
after `METRO_PORT_E2E` in `dismissDevScreens`, so local `.js.env` port
config is respected.
5. **`tests/jest.e2e.detox.config.js`** — Load `.js.env` via dotenv for
shared infra vars (`WATCHER_PORT`, `IOS_SIMULATOR`) alongside
`.e2e.env`. dotenv never overrides existing vars, so `.e2e.env` keys are
unaffected.
### Backwards compatibility
- `METRO_PORT_E2E` remains the primary port source everywhere
- CI configurations (`*.ci`) are unaffected — they still use release
apps and recovery-based launch
- `IOS_SIMULATOR` falls back to `iPhone 16 Pro` when unset
## **Changelog**
CHANGELOG entry: null
## **Related issues**
Fixes: TAT-2942
## **Manual testing steps**
```gherkin
Feature: Detox local debug builds
Scenario: Run Detox spec on custom simulator and port
Given .js.env has WATCHER_PORT=8062 and IOS_SIMULATOR=mm-2
And a debug build is installed on the mm-2 simulator
When user runs yarn test:e2e:ios:debug:run tests/smoke/perps/perps-position.spec.ts
Then Detox launches on mm-2 simulator (not iPhone 16 Pro)
And Metro deep link uses port 8062 (not 8081)
And dismissDevScreens connects to localhost:8062
Scenario: CI behavior unchanged
Given CI sets METRO_PORT_E2E and uses ios.sim.main.ci config
When CI runs Detox specs
Then launchAppWithRecovery is used (not launchAppForDebugBuild)
And METRO_PORT_E2E is used for port (WATCHER_PORT ignored)
```
## **Screenshots/Recordings**
### **Before**
<!-- N/A — test infrastructure, no UI changes -->
### **After**
<!-- N/A — test infrastructure, no UI changes -->
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk: changes are limited to Detox/Jest e2e test configuration,
but they do alter app launch routing and Metro port selection which
could affect local/CI test stability if misconfigured.
>
> **Overview**
> Improves Detox local debug e2e runs by making the iOS simulator and
Metro packager port configurable via env vars.
>
> Detox now (1) allows `IOS_SIMULATOR` to override the default iOS
device, (2) routes all non-`*.ci` configurations through the debug-build
launch path in `tests/helpers.js`, and (3) uses `METRO_PORT_E2E` with
`WATCHER_PORT` fallback for both deep-link packager URLs and
`dismissDevScreens`.
>
> Jest e2e config now loads `.js.env` after `.e2e.env` so shared infra
vars like `WATCHER_PORT` are available at runtime without overriding
test-specific env.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
8523269. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description** Fixes the block explorer URL generation for Solana SPL tokens in the Security Trust screen. The params.address contains a full CAIP asset type ID (e.g., solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB) but the block explorer URL template expects just the raw token address. This change extracts the assetReference from the CAIP asset type before passing it to getBlockExplorerTokenUrl. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Fix block explorer redirection for solana. ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-3076?focusedCommentId=412599 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> https://github.com/user-attachments/assets/a84d3264-4545-444f-961d-a3bf8e10a5a8 ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: a small, localized change to external link URL generation plus targeted unit tests; main risk is incorrect CAIP parsing leading to broken explorer links for some non-EVM assets. > > **Overview** > Fixes block explorer redirection from `SecurityTrustScreen` by detecting CAIP asset type addresses and passing only the parsed `assetReference` (e.g., Solana mint) into `getBlockExplorerTokenUrl` instead of the full CAIP identifier. > > Updates `SecurityTrustScreen.test.tsx` to make route params configurable and adds assertions that EVM addresses are passed through unchanged while Solana CAIP addresses are correctly parsed before URL generation (with `useBlockExplorer` now mocked to verify calls). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit a5464e1. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…tils, and test fixtures (#28925) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Removes all usages of the deprecated `tokensChainsCache` field from `TokenListController` across the codebase. This includes: - Deleting `app/selectors/tokenListController.ts` which exposed `selectTokenList`, `selectERC20TokensByChain`, and `selectERC20TokensByChainInternal` — all deprecated selectors that read from `tokensChainsCache` - Refactoring `selectAsset` and `assetToToken` in `assets-list.ts` to source `aggregators` directly from the token stored in `allTokens` (via `TokensController`) instead of looking it up in `tokensChainsCache` - Removing the early-return shortcut in `isSmartContractAddress` that checked `tokensChainsCache` before querying the network - Removing the `TokenListController.tokensChainsCache` mask from the Sentry state filter - Cleaning up all test fixtures and mocks that referenced `tokensChainsCache` <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: remove tokensChainsCache from assets selectors, transactions utils, and test fixtures ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-3058 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches asset-to-token mapping and contract-address detection behavior; mistakes could cause missing token metadata (e.g., `aggregators`) or extra network calls/perf regressions from removing the cache short-circuit. > > **Overview** > Removes the deprecated `TokenListController` selectors (`selectTokenList`, `selectERC20TokensByChain`) and updates callers/tests to no longer mock or depend on them. > > Updates `selectAsset` in `assets-list` to stop reading `TokenListController.tokensChainsCache`; `aggregators` (and `rwaData`) are now sourced from `TokensController.allTokens`, and related state fixtures/tests are adjusted accordingly. > > Simplifies `isSmartContractAddress` in `util/transactions` by dropping the mainnet token-cache short-circuit, and cleans up Sentry state masking to no longer reference `TokenListController.tokensChainsCache`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 016a367. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->
## **Description**
Fix perps glitch when pressing leverage.
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry:
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/reco
https://github.com/user-attachments/assets/89a84372-93ce-4a7f-9d5b-96e12b0392f1
rdings] -->
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk UI-state change confined to the leverage bottom sheet’s
visibility effect; main risk is behavioral regression in how/when the
sheet opens.
>
> **Overview**
> Prevents the Perps leverage bottom sheet from imperatively calling
`bottomSheetRef.current?.onOpenBottomSheet()` when `isVisible` becomes
true.
>
> The visibility effect now only runs the *reset-to-initial* logic when
the sheet closes (`!isVisible`), avoiding the open/reset sequencing that
caused the leverage-press glitch.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
156209e. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->
## **Description**
Adds `AuthenticationController` to the `social-service-messenger` to be
used by the core social package.
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: no-changelog
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Adds delegation for `AuthenticationController:getBearerToken` into the
SocialService messenger and upgrades `@metamask/social-controllers` to
`^1.0.0`, which could affect how auth tokens are fetched and used by
social API calls.
>
> **Overview**
> Enables SocialService code to request authentication by delegating
`AuthenticationController:getBearerToken` through
`getSocialServiceMessenger`, so the social controllers can fetch a
bearer token via the root messenger.
>
> Upgrades `@metamask/social-controllers` from `^0.2.0` to `^1.0.0` (and
updates `yarn.lock` accordingly), pulling in new transitive dependencies
(notably `@metamask/profile-sync-controller`).
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
a42cf50. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Antonio Regadas <antonio.regadas@consensys.net>
## **Description** AbortErrors from candle fetch cancellations during normal navigation/view teardown were treated as real errors and logged to Sentry at 3 service layers. Added `isAbortError()` utility and abort guards at all 3 catch blocks (`HyperLiquidClientService`, `MarketDataService`, `CandleStreamChannel`) to suppress expected cancellation noise while preserving real error reporting. Also adds two reusable agentic flows: - `perps/candle-rapid-switch` — cycles through BTC→ETH→SOL→HYPE→BTC→ETH and asserts no candle rate-limit or abort errors appear in logs. Reusable regression check for any PR touching the candle fetch path. - `perps/market-visit` — single-market atom (open detail → wait → back). Building block for composing multi-market navigation sequences. ## **Changelog** CHANGELOG entry: Fixed noisy Sentry error reports from expected candle fetch cancellations during navigation ## **Related issues** Fixes: [TAT-2971](https://consensyssoftware.atlassian.net/browse/TAT-2971) ## **Manual testing steps** ```gherkin Feature: Candle fetch cancellation handling Scenario: user navigates away from market detail during candle load Given the user is on the Perps BTC market detail screen And candle data is loading via WebSocket When user navigates away from the market detail screen Then no AbortError is logged to Sentry And candle data loaded successfully before navigation Scenario: rapid market switching does not trigger rate-limit errors Given the user is on the Perps market list When user rapidly opens and closes BTC, ETH, SOL, HYPE, BTC, ETH in sequence Then all candle charts load successfully And no candleSnapshot or rate-limit errors appear in logs Scenario: real candle fetch failure still reports Given the user is on the Perps BTC market detail screen When a real network error occurs during candle fetch Then the error is logged to Sentry normally ``` ## **Screenshots/Recordings** ### **Before** <!-- before.mp4 — recipe run on pre-fix code --> ### **After** <!-- after-rapid-switch-validation.mp4 — full recipe run including rapid switching across 6 markets --> https://github.com/user-attachments/assets/e5dc38ca-0aed-4d0e-a29f-1a2ce18fb9e2 ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. ## **Validation Recipe** <details> <summary>recipe.json</summary> ```json { "pr": "28953", "title": "Verify candle abort errors are not logged to Sentry", "jira": "TAT-2971", "acceptance_criteria": [ "Expected candle-request cancellations (AbortError) are not reported as errors to Sentry/Logger", "Real candle fetch failures still log/report normally to Sentry/Logger", "No new TypeScript errors introduced" ], "validate": { "static": ["yarn lint:tsc"], "workflow": { "pre_conditions": ["wallet.unlocked", "perps.feature_enabled"], "entry": "setup-nav-market", "nodes": { "setup-nav-market": { "action": "call", "ref": "perps/market-discovery", "params": { "symbol": "BTC" }, "next": "ac2-wait-candles" }, "ac2-wait-candles": { "action": "wait_for", "expression": "Engine.context.PerpsController.getMarketDataWithPrices().then(function(ms){var m=ms.find(function(x){return x.symbol==='BTC'});return JSON.stringify({found:!!m,price:m?m.price:'0'})})", "assert": { "operator": "not_null", "field": "price" }, "timeout_ms": 15000, "next": "ac2-screenshot-candles" }, "ac2-screenshot-candles": { "action": "screenshot", "filename": "evidence-ac2-candles-loaded.png", "next": "setup-nav-away" }, "setup-nav-away": { "action": "navigate", "target": "Wallet", "next": "setup-wait-teardown" }, "setup-wait-teardown": { "action": "wait", "ms": 500, "next": "ac1-log-check" }, "ac1-log-check": { "action": "log_watch", "window_seconds": 10, "must_not_appear": ["BUG_MARKER: abort error logged to Sentry"], "watch_for": ["CandleStreamChannel"], "next": "ac1-screenshot-clean-logs" }, "ac1-screenshot-clean-logs": { "action": "screenshot", "filename": "evidence-ac1-no-abort-noise.png", "next": "ac3-rapid-switch" }, "ac3-rapid-switch": { "action": "call", "ref": "perps/candle-rapid-switch", "params": { "screenshot_filename": "evidence-ac3-rapid-switch-chart.png" }, "next": "done" }, "done": { "action": "end", "status": "pass" } } } } } ``` </details> ## **Recipe Workflow** <details> <summary>workflow graph</summary> ```mermaid graph TD setup-nav-market["setup-nav-market<br/>call: perps/market-discovery"] --> ac2-wait-candles ac2-wait-candles["ac2-wait-candles<br/>wait_for: BTC price"] --> ac2-screenshot-candles ac2-screenshot-candles["ac2-screenshot-candles<br/>screenshot"] --> setup-nav-away setup-nav-away["setup-nav-away<br/>navigate: Wallet"] --> setup-wait-teardown setup-wait-teardown["setup-wait-teardown<br/>wait 500ms"] --> ac1-log-check ac1-log-check["ac1-log-check<br/>log_watch: no abort noise"] --> ac1-screenshot-clean-logs ac1-screenshot-clean-logs["ac1-screenshot-clean-logs<br/>screenshot"] --> ac3-rapid-switch ac3-rapid-switch["ac3-rapid-switch<br/>call: perps/candle-rapid-switch<br/>BTC→ETH→SOL→HYPE→BTC→ETH"] --> done done["done<br/>end: pass"] ``` </details> [TAT-2971]: https://consensyssoftware.atlassian.net/browse/TAT-2971?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
… sticky headers (#28933) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> Sports game detail screens had a mock outcomes tab with empty cards. This PR replaces the mocks with real `outcomeGroups` data, renders functional outcome cards grouped by market type, wires buy flow navigation, and adds a sticky tab bar + chip list header. **Provider layer:** - Added `line` and `shortTitle` fields to outcome types so buttons show compact labels (team abbreviations, `O/U` + line) while the buy screen preserves full names - Token titles for O/U markets now map `Yes/No` → `Over/Under` - Outcome sorting within standalone groups (points, assists, etc.) prioritizes volume descending - Unified all group keys to use underscores (was mixed hyphens/underscores) **UI layer:** - New `PredictGameOutcomesTab` component renders outcome cards from real data: composite groups show one card per subgroup (with line selector for multi-line markets), standalone groups show one card per outcome - Moneyline buttons use team colors; all others use neutral styling - Buy flow wired via `usePredictActionGuard` + `usePredictNavigation` - Tab bar and chip list combined into a single sticky `ScrollView` child - Chip selection scrolls outcomes to top - Chip state moved to `useGameDetailsTabs` hook ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: [PRED-810](https://consensyssoftware.atlassian.net/browse/PRED-810) [PRED-811](https://consensyssoftware.atlassian.net/browse/PRED-811) ## **Manual testing steps** ```gherkin Feature: Display outcomes in the outcomes tab Scenario: user views outcome cards for a sports game Given the user opens a sports game detail screen (NBA/Soccer) with the extended sports markets flag enabled When user sees the Outcomes tab Then the "Game Lines" chip is selected by default And Moneyline, Spreads, and Totals cards render with correct titles and prices And Moneyline buttons show team abbreviations with team colors And Spreads buttons show abbreviation + signed line (e.g., "ORL +1.5") And Totals buttons show "O 220.5" / "U 220.5" with neutral styling Scenario: user switches outcome group chips Given the user is viewing the Outcomes tab When user taps the "Points" chip Then the outcomes list scrolls to the top And player name cards render without the ": Points O/U" suffix And buttons show "O {line}" / "U {line}" labels And outcomes are sorted by volume descending Scenario: user taps an outcome button to buy Given the user is viewing outcome cards When user taps any outcome button Then the buy preview screen opens And the buy screen shows full team name or "Over"/"Under" (not abbreviated) And the correct market title and price are displayed Scenario: sticky tab bar and chip list Given the user is viewing the Outcomes tab When user scrolls down through outcome cards Then the tab bar and chip list stick together at the top of the screen And content does not bleed through the sticky header Scenario: feature flag is off Given the extended sports markets flag is disabled When user opens a sports game detail screen Then no chip list or outcome tabs are rendered And no sticky header behavior is applied ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** N/A ### **After** https://github.com/user-attachments/assets/2538ea49-a742-4986-b6b2-3baa8623d151 ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- Generated with the help of the pr-description AI skill --> [PRED-810]: https://consensyssoftware.atlassian.net/browse/PRED-810?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches both UI navigation (buy flow) and provider parsing/types for outcome/token data, so regressions could impact what markets render and which outcome/token gets passed into purchase. > > **Overview** > Replaces the mock sports market *Outcomes* tab with real `outcomeGroups` rendering via new `PredictGameOutcomesTab`, including subgroup cards (with optional line selection), volume subtitles, moneyline team-color buttons, and buy buttons that trigger guarded `navigateToBuyPreview`. > > Updates game details to show a combined sticky header (tab bar + chip list), moves chip state/visibility into `useGameDetailsTabs`, and adds chip auto-scroll behavior (`calculateChipScrollX`) plus chip-selection scroll-to-top logic for the outcomes list. > > Extends the Polymarket parsing/types to support `PredictOutcome.line` and `PredictOutcomeToken.shortTitle`, maps O/U `Yes/No` titles to `Over/Under`, adjusts outcome sorting tiebreakers, and standardizes outcome-group keys to underscore format; adds/updates unit tests and English i18n entries for group and market-type labels. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 9083f8e. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> Migrated `ListItem` component as part of pilot migration. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/DSYS-280 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** https://github.com/user-attachments/assets/afc628d9-29a8-458f-a524-48ac0f90b651 ### **After** https://github.com/user-attachments/assets/865bbc0a-6a2c-4cf8-82fa-fe6d7cc61101 ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > UI-only component migration with snapshot updates; main risk is minor layout/spacing/accessibility regressions in the settings drawer rows. > > **Overview** > Migrates `SettingsDrawer` from legacy list components (`ListItemColumn`/`WidthType`) to `@metamask/design-system-react-native` primitives (`ListItem` + `Box`) while preserving the same content structure (title/description/warning and optional arrow). > > Updates the `DefaultSettings` onboarding success Jest snapshot to reflect the new rendered tree/styles from the DSRN components. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 02bc58c. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…ntroller profileId (#28843) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** **Wire follow/unfollow persistence via SocialController state** - Bump @metamask/social-controllers to ^1.0.0 which writes followingProfileIds to controller state on follow/unfollow/updateFollowing - Add AuthenticationController:getBearerToken delegation to SocialService messenger (required by 1.0.0 for JWT auth on all API requests) - Hydrate following state once at Engine startup via SocialController:updateFollowing - Read isFollowing from Redux (SocialController.followingProfileIds) instead of ephemeral local state - toggleFollow calls SocialController:followTrader/unfollowTrader directly — controller updates state, Redux syncs, UI re-renders **Test plan** 1. Follow a trader on homepage carousel > navigate to leaderboard > follow state persists 2. Unfollow a trader on leaderboard > navigate away and back > unfollow state persists 3. Follow/unfollow on trader profile > navigate back to leaderboard > state is consistent 4. Kill and reopen app > follow state survives (controller state is persisted) [TSA-389](https://consensyssoftware.atlassian.net/browse/TSA-389) <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Wired up follow/unfollow functionality ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. [TSA-389]: https://consensyssoftware.atlassian.net/browse/TSA-389?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [TSA-401]: https://consensyssoftware.atlassian.net/browse/TSA-401?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Introduces new follow/unfollow wiring that calls `SocialController` via `Engine.controllerMessenger` and runs a new hydration request during `EngineService.start()`, which could affect app startup behavior and follow state consistency if messaging/auth fails. > > **Overview** > Moves follow state from local component overrides to **persisted `SocialController.followingProfileIds` in Redux**, via a new shared hook `useFollowToggle`/`useFollowToggleMany` that performs **optimistic follow/unfollow** and dispatches `SocialController:followTrader` / `SocialController:unfollowTrader` using the session `profileId` from `AuthenticationController`. > > Adds **engine-startup hydration** (`hydrateSocialFollowing`) to refresh the server following list by calling `SocialController:updateFollowing` (fire-and-forget, non-fatal on failure), plus a new selector `selectFollowingProfileIds` and expanded unit tests to cover seeding from controller state, optimistic updates, rejection reverts, and in-flight call de-duping. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 4637abc. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Xavier Brochard <xavier.brochard@consensys.net> Co-authored-by: Antonio Regadas <antonio.regadas@consensys.net>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Adds UTM parameters (`utm_source=mobile_app`) to outbound links in the MetaMask Mobile app, specifically updating the support page link to `https://support.metamask.io?utm_source=mobile_app`. Currently all mobile app traffic appears as "Direct" in analytics. This change enables proper attribution to distinguish mobile users from extension users and other sources. The solution updates link URLs in relevant components (help screens, settings, etc.) while maintaining identical user experience. ## **Changelog** CHANGELOG entry: Added UTM parameters to mobile app links for improved analytics tracking ## **Related issues** ## **Manual testing steps** ```gherkin Feature: UTM parameters on support links Scenario: Support link contains UTM parameters Given MetaMask Mobile app is running on test build And user navigates to Settings → Help When user taps the "Get help" / support link Then link URL contains "?utm_source=mobile_app" Scenario: External browser opens with correct UTM parameters Given MetaMask Mobile app is running on test build And user navigates to a screen with support link When user taps support link Then external browser opens https://support.metamask.io?utm_source=mobile_app ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches many user-facing outbound support links and `AppConstants` URL wiring; low functional complexity, but mistakes could send users to incorrect help pages or break deep-link constants. > > **Overview** > Adds a `MOBILE_UTM` suffix and expands `app/constants/urls.ts` to provide canonical, UTM-tagged MetaMask support/article URLs (plus shared deep-link base constants like `MM_UNIVERSAL_LINK_HOST` and `MM_ANDROID_BUNDLE_ID`). > > Updates a wide set of screens/modals (Support/Help, onboarding, password reset, staking/earn, perps, ramp region/eligibility, network verification, error boundary, etc.) to **stop using hardcoded support URLs** and instead reference these centralized constants, with corresponding test expectation updates. Also switches `AppConstants` to import several URL values and bundle/universal-link constants from `constants/urls` to avoid duplication. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 6ff5d04. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
#28974) ## **Description** This PR is limited to mobile app and mobile agentic validation improvements discovered while validating perps review flows on `mm-4`. Scope of this PR: - stabilize Perps modify-action selectors so live validation no longer depends on the accidental `undefined-*` selector path - tighten the mobile agentic recipe contract so invalid `wait_for.timeout` usage fails fast - make `validate-recipe.js` schema-validate before execution - copy screenshots into the passed artifact directory so validation proof stays with the run artifacts - document the canonical mobile agentic timing fields in `scripts/perps/agentic/README.md` Compatibility note: - default recipe artifact behavior is unchanged - only explicit `--artifacts-dir` runs now treat the provided path as the artifact root, so screenshots and run artifacts stay together under the requested directory Out of scope for this PR: - `.agents/skills/fs-cook` - `TRACKER.md` - `docs/readme/fs-cook*.md` - worker-template integration - wrapper skill work (`fs-review`, `fs-fixbug`) - Codex-vs-Claude recipe delegation work ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: - none ## **Manual testing steps** ```gherkin Feature: perps modify-action testability and mobile agentic validation contract Scenario: stable modify action selectors are available on the live BTC market details screen Given mm-4 is running MetaMask Mobile on PerpsMarketDetails for BTC When the user presses the modify button for the open position Then the modify action sheet selector appears And the stable flip option selector appears And the old undefined-derived selector is no longer needed Scenario: mobile agentic validation rejects invalid wait timing fields Given a recipe uses wait_for with timeout instead of timeout_ms When validate-flow-schema.js runs Then the recipe fails with an explicit schema error Scenario: screenshots are copied into the requested artifact directory Given validate-recipe.js runs a recipe with a screenshot step When the recipe passes Then the screenshot file is copied into the passed artifacts directory ``` ## **Screenshots/Recordings** ### **Before** - Live validation had to rely on `undefined-flip_position` - Successful screenshots lived outside the requested artifact root ### **After** - Live selector probe on `mm-4` confirms: - `perps-market-details-modify-button` - `perps-market-details-modify-action-sheet` - `perps-market-details-modify-action-sheet-flip_position` - Successful screenshots copy into the requested artifacts directory ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.
…28972) ## **Description** Fixes a crash that occurred when viewing token details on custom or unsupported networks (e.g., Fantom, Linea Sepolia, custom EVM chains). ### Issue When users navigated to token details on networks not supported by the Swaps/Bridge `formatAddressToAssetId`, the app would crash with: ``` Error: No XChain Swaps native asset found for chainId: eip155:59141 ``` **Reproduction Steps:** 1. Navigate to a custom network (e.g., Fantom with chainId `0xfa`) 2. Select any token on that network 3. App crashes when trying to display token details ### Solution Added a try-catch wrapper around the `formatAddressToAssetId` call in `Price.advanced.tsx`. When the function throws an error for unsupported chains: ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Fix navigation error on token details page when coming from custom network flow ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: a small defensive change that only affects advanced price chart initialization, with added tests covering unsupported-chain fallbacks. > > **Overview** > Prevents crashes in `PriceAdvanced` on unsupported/custom networks by wrapping `formatAddressToAssetId` in a `try/catch` and using an empty `assetId` when formatting fails, allowing the UI to **fall back to `PriceLegacy`** instead of throwing. > > Extends `Price.advanced.test.tsx` with coverage for custom/unsupported chainIds (including Linea Sepolia) and verifies `useOHLCVChart` is invoked with `assetId: ''` in the failure case, while supported networks still render the advanced chart. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 706896b. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…when pulling to refresh (#28655) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** When the user selects **"All popular networks"** and pulls to refresh on the NFT grid, `checkAndUpdateAllNftsOwnershipStatus` was only being called for a subset of the enabled networks — or potentially only mainnet — because the hook derived its chain list from `selectTokenNetworkFilter` (a `PreferencesController` value) intersected with `selectEvmNetworkConfigurationsByChainId` (networks the user has manually added). Any popular network the user hadn't explicitly added would be silently dropped. This fix replaces that incorrect source of truth with `chainIdsToDetectNftsFor` from the existing `useNftDetection` hook, which is already the canonical chain list used by `detectNfts()` itself (derived from `NetworkEnablementController.enabledNetworkMap`). Now both `detectNfts()` and `checkAndUpdateAllNftsOwnershipStatus()` operate on the exact same set of networks, regardless of which network filter the user has selected. Additionally updates `@metamask/assets-controllers` and removes the now-unused `AssetsContractController:getERC721OwnerOf` and `AssetsContractController:getERC1155BalanceOf` messenger action allowances from the NftController messenger (these were removed upstream). <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: fixed NFT ownership status not refreshing across all enabled networks when pulling to refresh ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-2959 & https://consensyssoftware.atlassian.net/browse/ASSETS-2976 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches NFT refresh behavior and upgrades `@metamask/assets-controllers`, which could subtly change which networks are queried and how the NFT controller interacts with upstream controller APIs. > > **Overview** > Fixes pull-to-refresh on the NFT grid so ownership status updates run across the **same enabled chain set** used by NFT detection. `useNftRefresh` now derives network client IDs from `useNftDetection().chainIdsToDetectNftsFor` (instead of `selectTokenNetworkFilter`), ensuring all enabled/popular networks get `checkAndUpdateAllNftsOwnershipStatus` calls. > > Updates unit tests to cover the "All popular networks" case, empty-enabled-chain behavior, and undefined client IDs. Also bumps `@metamask/assets-controllers` to `^104.0.0` and removes now-unused messenger action allowances (`AssetsContractController:getERC721OwnerOf`, `AssetsContractController:getERC1155BalanceOf`). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 4df107d. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->
## **Description**
Fixes an issue where the price and percentage display would remain stuck
at crosshair hover values after changing timeframes in the advanced
chart.
**Issue**
When a user:
Hovers over the chart (which sets crosshair data)
Changes to a different timeframe (or clicks the same timeframe again)
The price and percentage display would incorrectly show the old
crosshair values instead of resetting to show the current values for the
new timeframe.
The crosshairData state was not being cleared when changing timeframes.
**Solution**
Added setCrosshairData(null) in the handleTimeRangeSelect callback to
clear crosshair data whenever the timeframe changes.
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: reset crosshair on timeRange change
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk UI-state fix that only clears `crosshairData` when switching
chart time ranges, affecting display state but not data fetching or
persistence.
>
> **Overview**
> Fixes the advanced token chart header getting stuck showing crosshair
hover price/percentage after changing timeframes by clearing
`crosshairData` in `handleTimeRangeSelect` before updating the selected
range and tracking the event.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
6a6551e. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…28973) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> This PR adds support for universal links from Braze push notification deeplinks. It also removes the interstitial from this source, alongside all trusted sources (carousels, push notifications, Braze push notifications and in-app notifications). Relevant documentation: https://www.braze.com/docs/developer_guide/push_notifications/deep_linking?tab=objective-c&sdktab=swift https://www.braze.com/docs/partners/message_orchestration/deeplinking/branch_for_deeplinking/?tab=objective-c ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/GE-188 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` Cold & Hot Start: Deeplink Flow Requirements 1. Open deeplinks without interstitial Send test notifications with deeplinks from Braze and NaaP → Expect: Direct open, no interstitial 2. Open deeplinks with interstitial Open deeplinks from your notes Open a deeplink from a QR code (e.g., [generated here](https://fr.qr-code-generator.com/)) pointing to: https://link.metamask.io/trending → Expect: Interstitial displayed before opening ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes deep-link routing and interstitial behavior for several in-app origins, plus adds iOS-native Braze URL interception, which could affect notification/universal-link navigation and analytics flows if misrouted. > > **Overview** > Enables Braze push-notification deep links on iOS to correctly resolve **universal links** by forwarding Branch domains from `BrazeDelegate.shouldOpenURL` to Branch, while suppressing Braze’s default URL opening to avoid duplicate deliveries. > > Updates deep-link interstitial logic in `handleUniversalLink` so a defined set of **trusted in-app sources** (carousel, in-app notification, push notification, Braze) skip the interstitial for both *public and private* links; other in-app sources now show the modal. The Braze JS listener is no longer Android-gated, and corresponding tests are updated. > > Bumps mobile build numbers (`versionCode`/`CURRENT_PROJECT_VERSION`/Bitrise version numbers) to `4543`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit ee0c232. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Contributor
🔍 Smart E2E Test Selection⏭️ Smart E2E selection skipped - draft PR All E2E tests pre-selected. |
|
Contributor
|
✅ E2E Fixture Validation — Schema is up to date |
chloeYue
approved these changes
May 4, 2026
Contributor
|
policy-bot: approve |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



🚀 v7.75.0 Testing & Release Quality Process
Hi Team,
As part of our new MetaMask Release Quality Process, here’s a quick overview of the key processes, testing strategies, and milestones to ensure a smooth and high-quality deployment.
📋 Key Processes
Testing Strategy
Conduct regression and exploratory testing for your functional areas, including automated and manual tests for critical workflows.
Focus on exploratory testing across the wallet, prioritize high-impact areas, and triage any Sentry errors found during testing.
Validate new functionalities and provide feedback to support release monitoring.
GitHub Signoff
Issue Resolution
Cherry-Picking Criteria
🗓️ Timeline and Milestones
✅ Signoff Checklist
Each team is responsible for signing off via GitHub. Use the checkbox below to track signoff completion:
Team sign-off checklist
This process is a major step forward in ensuring release stability and quality. Let’s stay aligned and make this release a success! 🚀
Feel free to reach out if you have questions or need clarification.
Many thanks in advance
Reference